import { 
  BackSide,
  CatmullRomCurve3,
  Float32BufferAttribute,
  Geometry,
  HemisphereLight,
  Line,
  Mesh,
  MeshBasicMaterial,
  Path,
  PerspectiveCamera, 
  QuadraticBezierCurve3, 
  Scene, 
  SplineCurve, 
  TubeBufferGeometry, 
  Vector2, 
  Vector3, 
  WebGLRenderer 
} from "three"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { interpolateHsl } from 'd3-interpolate'
import TWEEN from '@tweenjs/tween.js'
import stats from '../utils/stats'

const scene = new Scene()
const camera = new PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000)
// 不能设置为0
camera.position.set(500, 100, 50)

const renderer = new WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setClearColor(0x000000)
renderer.setSize(window.innerWidth, window.innerHeight)

document.body.appendChild(renderer.domElement)

new OrbitControls(camera, renderer.domElement)

const light = new HemisphereLight(0xffffff, 0xcccccc, 1)
scene.add(light)

const renderScene = new RenderPass(scene, camera)
const bloomPass = new UnrealBloomPass(
  new Vector2(window.innerWidth, window.innerHeight),
  1.5,
  0.4,
  0.85
)
bloomPass.threshold = 0.3
bloomPass.strength = 2
bloomPass.radius = 0.3

const bloomComposer = new EffectComposer(renderer)
bloomComposer.addPass(renderScene)
bloomComposer.addPass(bloomPass)

// 生成曲线
const startVec = new Vector3(500, 0, 0)
const controlVec = new Vector3(-400, 0, 20)
const endVec = new Vector3(-500, 0, 300)
const curve = new QuadraticBezierCurve3(startVec, controlVec, endVec);

// 直线模式
const line = new CatmullRomCurve3([
  new Vector3(0, 0, 0),
  new Vector3(100, 0, 100),
  new Vector3(0, 0, 100),
])
// const geometry = new TubeBufferGeometry(line, 20, 2, 8, false)

// 管道缓冲几何体
const geometry = new TubeBufferGeometry(curve, 20, 2, 8, false)
// 
const material = new MeshBasicMaterial({ 
  // 使用顶点着色
  vertexColors: true, 
  // 渲染正面
  side: BackSide
})

const count = geometry.attributes.position.count
const rgbInterpolate = interpolateHsl('#00ffff', '#000000')
const colorArr = new Array(count)

for (let i = 0; i < count; i++) {
  const t = i / count
  const rgb = rgbInterpolate(t)
  const rgbVal = rgb.match(/\d+/g)

  const r = Number(rgbVal[0]) / 255
  const g = Number(rgbVal[1]) / 255
  const b = Number(rgbVal[2]) / 255

  colorArr[3 * i] = r
  colorArr[3 * i + 1] = g
  colorArr[3 * i + 2] = b
}

geometry.setAttribute('color', new Float32BufferAttribute(colorArr, 3))
const mesh = new Mesh(geometry, material)
scene.add(mesh)

function lightMove() {
  new TWEEN
    .Tween({value: 0})
    .to({value: 1}, 1000)
    .onUpdate(val => {
      const anchor = Number((val.value * count).toFixed(0))
      const b = colorArr.slice(anchor * 3)
      const f = colorArr.slice(0, anchor * 3)
      const newColorArr = [].concat(<[]>b, <[]>f)
      mesh.geometry.setAttribute('color', new Float32BufferAttribute(newColorArr, 3))
    })
    .start()
    .repeat(Infinity)
}

const animate = function() {
  TWEEN.update()
  stats.update()

  bloomComposer.render()
  requestAnimationFrame(animate)
}

animate()

lightMove()